import CreateKnowledgeGraph from './CreateKnowledgeGraph'

// 力导图模式
export default class ForceMod extends CreateKnowledgeGraph {
  constructor(options) {
    super(options)
    this.forceSimulation = null // 力导向图
    this.links = null
    this.gs = null
    this.circles = null
    this.texts = null
  }

  // 力导图模式初始化
  forceModInit(){
    console.log(this.data,'力导图模式初始化')

    // 初始化力导图
    this.forceInit()
    // 初始化数据
    this.dataInit()
    // 初始化元素
    this.domInit()
    // 初始化拖拽
    this.dragInit()
    // 初始化事件
    this.emitInit()
    // 移动元素到屏幕中央
    this.setCenter()
    // 初始化隐藏状态
    this.changeHideType()
  }

  // 初始化力导图
  forceInit(){
    // 新建力引导图
    this.forceSimulation = this.d3
      .forceSimulation()
      .force('link', this.d3.forceLink().links(this,this.data.lineList))
      .force('collide', this.d3.forceCollide().radius((d) => this.config.nodeSize[d.level].r))
  }

  // 初始化数据
  dataInit(){
    // 初始化力导向图,生成节点数据
    this.forceSimulation.nodes(this.data.nodeList)

    // 生成边数据
    this.forceSimulation
      .force('link')
      .id((d)=>d.id)
      .links(this.data.lineList)
      .distance((d)=>{
        let long = 130
        if (d.source.level==0) {
          long = 370
        }
        return long
      })

    // 环形布局初始化
    if(!localStorage.getItem('forceDataJSON') || this.isInitialize){
      this.circularInit()
    }
  }

  // 环形布局初始化
  circularInit(){
    // 遍历一级节点
    const levelOneNodes = this.data.nodeList.filter(node => node.level === 1)
    // 计算圆形轨迹
    this.calculateCircular(levelOneNodes,370,0,0)

    // 遍历二级节点
    const result = this.data.lineList.reduce((acc, cur) => {
      const source = cur.source
      const target = cur.target
      if (this.data.nodeList.find(item=>item.id==cur.source.id).level==1) {
        if (!acc[source.id]) {
          acc[source.id] = []
        }
        acc[source.id].push(this.data.nodeList.find((item)=>item.id==target.id))
      }
      return acc
    }, {})
    for (const key in result) {
      if (Object.prototype.hasOwnProperty.call(result, key)) {
        const parentNode = this.data.nodeList.find(item=> (item.id==key && item.level==1))
        const element = result[key]
        // 计算圆形轨迹
        this.calculateCircular(element,130,parentNode.x,parentNode.y)
      }
    }
  }

  // 初始化元素
  domInit(){
    // 设置color的颜色比例尺
    const colorScale = this.d3.scaleOrdinal().domain(this.d3.range(this.data.nodeList.length)).range(this.d3.schemeCategory10)

    // 有了节点和边的数据后，绘制边
    this.links = this.graphInfo.collectionZoom
      .append('g')
      .selectAll('line')
      .data(this.data.lineList)
      .enter()
      .append('line')
      .attr('stroke', (d) => colorScale(d.source.level))
      .attr('stroke-width', 1)
      .attr('class',(d)=> `d_groupsLevel_${d.source.level}`)


    // 绘制节点，先为节点和节点上的文字分组
    this.gs = this.graphInfo.collectionZoom
      .selectAll('.circleText')
      .data(this.data.nodeList)
      .enter()
      .append('g')
      .attr('transform', function (d) {
        const cirX = d.x
        const cirY = d.y
        return 'translate(' + cirX + ',' + cirY + ')'
      })
      .attr('class',(d)=> `d_groupsLevel_${d.level}`)

    // 绘制圆形
    this.circles = this.gs.append('circle')
      .attr('r', (d) => this.config.nodeSize[+d.level].r )
      .attr('fill', (d) => colorScale(d.level))
      .attr('fill-opacity',0.7)
      .attr('stroke','#fff')
      .attr('stroke-width','1')
      .attr('class','d_circle')

    // 绘制文字
    this.texts = this.gs.append('text')
      .attr('x', 0)
      .attr('y', (d)=>0-(this.config.nodeSize[+d.level].fontSize/6))
      .attr('dy', 10)
      .attr('text-anchor', 'middle')
      .attr('font-size',(d) => this.config.nodeSize[+d.level].fontSize)
      .attr('fill','#fff')
      .text(function (d) {
        return d.name
      })
      .attr('class','d_text')
  }

  // 初始化拖拽
  dragInit(){
    this.gs.call(this.d3.drag()
      .on('start', (d)=>{
        // 开始拖动
        if (!d.active) {
          this.forceSimulation.alphaTarget(0.8).restart()
        }
        d.subject.fx = d.subject.x
        d.subject.fy = d.subject.y
      })
      .on('drag', (d)=>{
        // 拖动中
        d.subject.fx = d.x
        d.subject.fy = d.y
      })
      .on('end', (d)=>{
        // 结束拖动
        if (!d.active) {
          this.forceSimulation.alphaTarget(0)
        }
        d.subject.fx = null
        d.subject.fy = null
      }))

    this.forceSimulation.on('tick', ()=>{
      this.links
        .attr('x1', function (d) {
          return d.source.x
        })
        .attr('y1', function (d) {
          return d.source.y
        })
        .attr('x2', function (d) {
          return d.target.x
        })
        .attr('y2', function (d) {
          return d.target.y
        })
      this.gs.attr('transform', function (d) {
        return 'translate(' + d.x + ',' + d.y + ')'
      })
    })
  }

  // 初始化事件
  emitInit(){
    this.texts.on('click',this.config.handleClick)
  }

  // 初始化按钮
  initialize(data){
    this.graphInfo.collectionZoom.selectAll('*').remove()
    this.data = JSON.parse(JSON.stringify(data))
    this.isInitialize = true
    this.forceModInit()
  }

  // 切换主题
  changeThemeInside(theme){
    this.changeTheme(theme)
  }

  // 保存
  handleSave(){
    this.save(()=>{
      const saveData = {
        nodeList:this.data.nodeList,
        lineList:JSON.parse(JSON.stringify(this.originalData)).lineList
      }
      const forceDataJSON = JSON.stringify(saveData)
      localStorage.setItem('forceDataJSON', forceDataJSON)
    })
  }
}
